package com.binary.coder.gift.core.infrastructure.repository.invitation;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.binary.coder.gift.core.common.bean.PageBean;
import com.binary.coder.gift.core.common.constant.InvitationEntrustStatus;
import com.binary.coder.gift.core.common.constant.InvitationPermissionType;
import com.binary.coder.gift.core.domain.invitation.model.aggregate.HandleInvitationRecordAggregate;
import com.binary.coder.gift.core.domain.invitation.model.aggregate.InvitationCardAggregate;
import com.binary.coder.gift.core.domain.invitation.model.entity.InvitationEntrustEntity;
import com.binary.coder.gift.core.domain.invitation.model.entity.InvitationRecordEntity;
import com.binary.coder.gift.core.domain.invitation.repository.InvitationRepository;
import com.binary.coder.gift.core.infrastructure.mapper.invitation.*;
import com.binary.coder.gift.core.infrastructure.po.invitation.*;
import com.binary.coder.gift.core.interfaces.Invitation.dto.req.PageQueryInvitationCardReq;
import com.binary.coder.gift.core.interfaces.Invitation.dto.req.PageQueryInvitationEntrustReq;
import com.binary.coder.gift.core.interfaces.Invitation.dto.res.QueryInvitationEntrustRes;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author atao
 * @version 1.0.0
 * @ClassName InvitationRepository.java
 * @Description Invitation仓储接口
 * @createTime 2024年06月21日 16:55:00
 */
@Repository
public class InvitationRepositoryImpI implements InvitationRepository {

    @Resource
    private DesignElementMapper designElementMapper;

    @Resource
    private InvitationCardMapper invitationCardMapper;

    @Resource
    private InvitationPermissionMapper invitationPermissionMapper;

    @Resource
    private InvitationRecordMapper invitationRecordMapper;

    @Resource
    private InvitationEntrustMapper invitationEntrustMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveOrUpdateInvitation(InvitationCardAggregate invitationCardAggregate) {
        InvitationCard invitationCard = invitationCardAggregate.getInvitationCard();
        // 1. 保存请帖
        int i = invitationCardMapper.updateById(invitationCard);
        if (i < 0) {
            invitationCardMapper.insert(invitationCard);
            // 1.1 添加编辑权限
            InvitationPermission invitationPermission = invitationCardAggregate.getInvitationPermission(invitationCard.getId(), InvitationPermissionType.WRITE.getTypeCode());
            invitationPermissionMapper.insert(invitationPermission);
        }
        // 2. 保存请帖的当前元素
        List<DesignElement> designElementList = invitationCardAggregate.getDesignElementList(invitationCard.getId());
        designElementList.forEach(e -> {
            designElementMapper.insert(e);
        });
        return invitationCard.getId();
    }


    @Override
    public void deleteInvitationCardById(Long invitationCardId) {
        // 1. 删除请帖
        invitationCardMapper.deleteById(invitationCardId);
        // 2. 删除请帖的当前元素
        designElementMapper.delete(Wrappers.lambdaQuery(DesignElement.class).eq(DesignElement::getPosterId, invitationCardId));
    }

    @Override
    public PageBean<InvitationCardAggregate> pageQueryInvitationCard(PageQueryInvitationCardReq req) {
        LambdaQueryWrapper<InvitationCard> queryWrapper = Wrappers.lambdaQuery(InvitationCard.class);
        if (Objects.nonNull(req.getUserId())) {
            queryWrapper = queryWrapper.eq(InvitationCard::getUserId, req.getUserId());
        }
        if (Objects.nonNull(req.getInvitationType())) {
            queryWrapper = queryWrapper.eq(InvitationCard::getTypeCode, req.getInvitationType());
        }
        Page<InvitationCard> invitationCardPage = invitationCardMapper.selectPage(new Page<>(req.getPageIndex(), req.getPageSize()), queryWrapper);
        // 结果装配
        PageBean<InvitationCardAggregate> res = new PageBean<>(invitationCardPage.getCurrent(), invitationCardPage.getSize(), invitationCardPage.getTotal());
        res.setRecords(invitationCardPage.getRecords().stream()
                .map(e -> {
                    List<DesignElement> designElements = designElementMapper.selectList(Wrappers.lambdaQuery(DesignElement.class).eq(DesignElement::getPosterId, e.getId()));
                    return InvitationCardAggregate.buildInvitationCardAggregate(e, designElements);
                }).collect(Collectors.toList())
        );
        return res;
    }

    @Override
    public void saveInvitationRecord(InvitationRecordEntity entity) {
        InvitationRecord invitationRecord = entity.getInvitationRecord();
        int i = invitationRecordMapper.updateById(invitationRecord);
        if (i <= 0) {
            invitationRecordMapper.insert(invitationRecord);
        }
    }

    @Override
    public InvitationCardAggregate queryInvitationCard(Long invitationCardId) {
        InvitationCard invitationCard = invitationCardMapper.selectById(invitationCardId);
        List<DesignElement> designElements = designElementMapper.selectList(Wrappers.lambdaQuery(DesignElement.class).eq(DesignElement::getPosterId, invitationCard.getId()));
        return InvitationCardAggregate.buildInvitationCardAggregate(invitationCard, designElements);
    }

    @Override
    public HandleInvitationRecordAggregate queryInvitationRecord(Long userId, Long invitationCardId) {
        InvitationRecord invitationRecord = invitationRecordMapper.selectOne(Wrappers.lambdaQuery(InvitationRecord.class).eq(InvitationRecord::getUserId, userId).eq(InvitationRecord::getInvitationId, invitationCardId));
        return HandleInvitationRecordAggregate.build(invitationRecord);
    }

    @Override
    public PageBean<HandleInvitationRecordAggregate> pageQueryInvitationRecord(long pageIndex, long pageIndex1, Long invitationId) {
        Page<InvitationRecord> invitationRecordPage = invitationRecordMapper.selectPage(new Page<>(pageIndex, pageIndex1), Wrappers.lambdaQuery(InvitationRecord.class).eq(InvitationRecord::getInvitationId, invitationId));
        PageBean<HandleInvitationRecordAggregate> res = new PageBean<>(invitationRecordPage.getCurrent(), invitationRecordPage.getSize(), invitationRecordPage.getTotal());
        res.setRecords(invitationRecordPage.getRecords().stream().map(HandleInvitationRecordAggregate::build).collect(Collectors.toList()));
        return res;
    }

    @Override
    public void saveInvitationEntrust(InvitationEntrustEntity invitationEntrustEntity) {
        InvitationEntrust invitationEntrust = BeanUtil.copyProperties(invitationEntrustEntity, InvitationEntrust.class);
        invitationEntrust.setProcessStatus(InvitationEntrustStatus.UN_PROCESS.getStatusCode());
        invitationEntrustMapper.insert(invitationEntrust);
    }

    @Override
    public PageBean<QueryInvitationEntrustRes> pageQueryInvitationEntrust(PageQueryInvitationEntrustReq req) {
        LambdaQueryWrapper<InvitationEntrust> queryWrapper = Wrappers.lambdaQuery(InvitationEntrust.class);
        if (StringUtils.isNotEmpty(req.getName())) {
            queryWrapper = queryWrapper.like(InvitationEntrust::getName, req.getName());
        }
        if (Objects.nonNull(req.getEntrustStartTime())) {
            queryWrapper = queryWrapper.ge(InvitationEntrust::getCreateTime, req.getEntrustStartTime());
        }
        if (Objects.nonNull(req.getEntrustEndTime())) {
            queryWrapper = queryWrapper.le(InvitationEntrust::getCreateTime, req.getEntrustEndTime());
        }
        if (Objects.nonNull(req.getPriceDesc())) {
            queryWrapper = req.getPriceDesc() ? queryWrapper.orderByDesc(InvitationEntrust::getPrice) : queryWrapper.orderByAsc(InvitationEntrust::getPrice);
        }
        Page<InvitationEntrust> invitationEntrustPage = invitationEntrustMapper.selectPage(new Page<>(req.getPageIndex(), req.getPageSize()), queryWrapper);
        // 装配
        PageBean<QueryInvitationEntrustRes> res = new PageBean<>(invitationEntrustPage.getCurrent(), invitationEntrustPage.getSize(), invitationEntrustPage.getTotal());
        res.setRecords(invitationEntrustPage.getRecords().stream().map(e -> BeanUtil.copyProperties(e, QueryInvitationEntrustRes.class)).collect(Collectors.toList()));
        return res;
    }
}
